package com.carey.blog.repository.impl;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;

import com.carey.blog.framework.latke.model.Role;
import com.carey.blog.framework.latke.model.User;
import com.carey.blog.framework.latke.repository.RepositoryException;
import com.carey.blog.framework.latke.repository.gae.AbstractGAERepository;
import com.carey.blog.repository.UserRepository;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

/**
 * User Google App Engine repository.
 * 
 */
public final class UserGAERepository extends AbstractGAERepository implements
		UserRepository {

	/**
	 * Logger.
	 */
	private static final Logger LOGGER = Logger
			.getLogger(UserGAERepository.class.getName());

	@Override
	public String getName() {
		return User.USER;
	}

	@Override
	public JSONObject getByEmail(final String email) {
		final String cacheKey = "GetByEmail[" + email + "]";
		JSONObject ret = (JSONObject) CACHE.get(cacheKey);
		if (null == ret) {
			final Query query = new Query(getName());
			query.addFilter(User.USER_EMAIL, Query.FilterOperator.EQUAL,
					email.toLowerCase());
			final PreparedQuery preparedQuery = getDatastoreService().prepare(
					query);
			final Entity entity = preparedQuery.asSingleEntity();
			if (null == entity) {
				return null;
			}

			ret = entity2JSONObject(entity);

			CACHE.put(cacheKey, ret);
		}

		return ret;
	}

	@Override
	public JSONObject getAdmin() {
		final String cacheKey = "GetAdmin";
		JSONObject ret = (JSONObject) CACHE.get(cacheKey);
		if (null == ret) {
			final Query query = new Query(getName());
			query.addFilter(User.USER_ROLE, Query.FilterOperator.EQUAL,
					Role.ADMIN_ROLE);
			final PreparedQuery preparedQuery = getDatastoreService().prepare(
					query);
			final Entity entity = preparedQuery.asSingleEntity();
			if (null == entity) {
				return null;
			}

			ret = entity2JSONObject(entity);

			CACHE.put(cacheKey, ret);
		}

		return ret;
	}

	@Override
	public boolean isAdminEmail(final String email) throws RepositoryException {
		final JSONObject user = getByEmail(email);

		if (null == user) {
			return false;
		}

		try {
			return Role.ADMIN_ROLE.equals(user.getString(User.USER_ROLE));
		} catch (final JSONException e) {
			LOGGER.log(Level.SEVERE, e.getMessage(), e);

			throw new RepositoryException(e);
		}
	}

	/**
	 * Gets the {@link UserGAERepository} singleton.
	 * 
	 * @return the singleton
	 */
	public static UserGAERepository getInstance() {
		return SingletonHolder.SINGLETON;
	}

	/**
	 * Private default constructor.
	 */
	private UserGAERepository() {
	}

	/**
	 * Singleton holder.
	 * 
	 */
	private static final class SingletonHolder {

		/**
		 * Singleton.
		 */
		private static final UserGAERepository SINGLETON = new UserGAERepository();

		/**
		 * Private default constructor.
		 */
		private SingletonHolder() {
		}
	}
}
